const std = @import("std");
const Allocator = std.mem.Allocator;
const virtual_actor = @import("virtual_actor.zig");

/// Actor 系统配置
pub const ActorSystemConfig = struct {
    /// 是否启用集群模式
    cluster_mode: bool = false,
    
    /// 空闲超时（秒）
    idle_timeout: i64 = 300,
    
    /// 持久化配置
    persistence: PersistenceConfig = .{},
    
    /// 集群配置
    cluster: ?ClusterConfig = null,
};

pub const PersistenceConfig = struct {
    type: PersistenceType = .memory,
    connection_string: ?[]const u8 = null,
};

pub const PersistenceType = enum {
    memory,
    redis,
    postgresql,
};

pub const ClusterConfig = struct {
    nodes: []const []const u8,
    port: u16 = 7001,
};

/// Actor 系统 - Orleans 风格的 Virtual Actor 系统
pub const ActorSystem = struct {
    allocator: Allocator,
    config: ActorSystemConfig,
    registry: virtual_actor.ActorRegistry,
    gc_thread: ?std.Thread = null,
    running: bool = false,
    
    pub fn init(allocator: Allocator, config: ActorSystemConfig) !ActorSystem {
        var system = ActorSystem{
            .allocator = allocator,
            .config = config,
            .registry = virtual_actor.ActorRegistry.init(allocator, config.idle_timeout),
            .gc_thread = null,
            .running = true,
        };
        
        // 启动垃圾回收线程
        system.gc_thread = try std.Thread.spawn(.{}, gcLoop, .{&system});
        
        return system;
    }
    
    pub fn deinit(self: *ActorSystem) void {
        self.running = false;
        
        if (self.gc_thread) |thread| {
            thread.join();
        }
        
        self.registry.deinit();
    }
    
    /// 获取 Actor（自动激活）
    pub fn getActor(
        self: *ActorSystem,
        comptime ActorType: type,
        id: []const u8,
        storage: anytype,
    ) !*ActorType {
        const actor_id = virtual_actor.ActorId{
            .type_name = @typeName(ActorType),
            .id = id,
        };
        
        return try self.registry.getOrCreate(ActorType, actor_id, storage);
    }
    
    /// 垃圾回收循环 - 定期失活空闲的 Actor
    fn gcLoop(self: *ActorSystem) void {
        while (self.running) {
            std.time.sleep(60 * std.time.ns_per_s); // 每分钟检查一次
            
            // TODO: 需要传入正确的 storage
            // self.registry.deactivateIdle(storage) catch |err| {
            //     std.debug.print("GC error: {}\n", .{err});
            // };
        }
    }
};

/// 消息队列 - 用于 Actor 间通信
pub fn MessageQueue(comptime MessageType: type) type {
    return struct {
        const Self = @This();
        
        allocator: Allocator,
        queue: std.ArrayList(MessageType),
        mutex: std.Thread.Mutex,
        cond: std.Thread.Condition,
        
        pub fn init(allocator: Allocator) Self {
            return .{
                .allocator = allocator,
                .queue = std.ArrayList(MessageType).init(allocator),
                .mutex = .{},
                .cond = .{},
            };
        }
        
        pub fn deinit(self: *Self) void {
            self.queue.deinit();
        }
        
        pub fn push(self: *Self, msg: MessageType) !void {
            self.mutex.lock();
            defer self.mutex.unlock();
            
            try self.queue.append(msg);
            self.cond.signal();
        }
        
        pub fn pop(self: *Self) ?MessageType {
            self.mutex.lock();
            defer self.mutex.unlock();
            
            if (self.queue.items.len == 0) {
                return null;
            }
            
            return self.queue.orderedRemove(0);
        }
        
        pub fn wait(self: *Self, timeout_ns: u64) ?MessageType {
            self.mutex.lock();
            defer self.mutex.unlock();
            
            if (self.queue.items.len == 0) {
                self.cond.timedWait(&self.mutex, timeout_ns) catch {};
            }
            
            if (self.queue.items.len == 0) {
                return null;
            }
            
            return self.queue.orderedRemove(0);
        }
    };
}

/// Turn-based 并发模型 - Orleans 的核心特性
/// 每个 Actor 串行处理消息，保证单线程执行
pub fn TurnBasedExecutor(comptime ActorType: type, comptime MessageType: type) type {
    return struct {
        const Self = @This();
        
        actor: *ActorType,
        queue: MessageQueue(MessageType),
        thread: ?std.Thread = null,
        running: bool = false,
        
        pub fn init(allocator: Allocator, actor: *ActorType) Self {
            return .{
                .actor = actor,
                .queue = MessageQueue(MessageType).init(allocator),
                .thread = null,
                .running = false,
            };
        }
        
        pub fn deinit(self: *Self) void {
            self.stop();
            self.queue.deinit();
        }
        
        pub fn start(self: *Self, handler: *const fn(*ActorType, MessageType) anyerror!void) !void {
            if (self.running) return error.AlreadyRunning;
            
            self.running = true;
            self.thread = try std.Thread.spawn(.{}, runLoop, .{self, handler});
        }
        
        pub fn stop(self: *Self) void {
            if (!self.running) return;
            
            self.running = false;
            if (self.thread) |thread| {
                thread.join();
                self.thread = null;
            }
        }
        
        pub fn send(self: *Self, msg: MessageType) !void {
            try self.queue.push(msg);
        }
        
        fn runLoop(self: *Self, handler: *const fn(*ActorType, MessageType) anyerror!void) void {
            while (self.running) {
                if (self.queue.wait(1_000_000_000)) |msg| { // 1 秒超时
                    // 串行处理消息
                    handler(self.actor, msg) catch |err| {
                        std.debug.print("Actor handler error: {}\n", .{err});
                    };
                    
                    // 更新最后访问时间
                    self.actor.touch();
                }
            }
        }
    };
}

test "Actor System 初始化" {
    const testing = std.testing;
    
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();
    
    var system = try ActorSystem.init(allocator, .{
        .cluster_mode = false,
        .idle_timeout = 300,
    });
    defer system.deinit();
    
    try testing.expect(system.running);
}

test "消息队列" {
    const testing = std.testing;
    
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();
    
    var queue = MessageQueue(u32).init(allocator);
    defer queue.deinit();
    
    try queue.push(1);
    try queue.push(2);
    try queue.push(3);
    
    try testing.expect(queue.pop().? == 1);
    try testing.expect(queue.pop().? == 2);
    try testing.expect(queue.pop().? == 3);
    try testing.expect(queue.pop() == null);
}
